-- 星曜之门-星耀之力
local ObjHuman = require("core.ObjHuman")
local Util = require("common.Util")
local Msg = require("core.Msg")
local Broadcast = require("broadcast.Broadcast")
local Lang = require("common.Lang")
local BagLogic = require("bag.BagLogic")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local XingYaoMenExcel = require("excel.xingYaoMen")
local HeroGrid = require("hero.HeroGrid")
local Grid = require("bag.Grid")
local RoleAttr = require("role.RoleAttr")
local ItemDefine = require("bag.ItemDefine")
local HeroExcel = require("excel.hero")

-- human.db.XingYaoPower[camp] = {
-- 	lv, --等级
-- 	lvAttrs, --进度增加的属性，升级清除 lvAttrs[key] = value
--	exp, --经验
-- 	qualityID --品阶id对应配置表
-- }

-- human.db.XingYaoPower.resetCnt --重置次数

function updateDaily(human)
	if not human.db.XingYaoPower then return end

	human.db.XingYaoPower.resetCnt = nil
end

local function getPowerData(human,camp)
	if not human.db.XingYaoPower then return end

	return human.db.XingYaoPower[camp]
end

function GC_XINGYAOMEN_POWER_REDS(human,camp)
	local msgRet = Msg.gc.GC_XINGYAOMEN_POWER_REDS
	local lvRed = lvRed(human,camp)
	local qualityRed = qualityRed(human,camp)
	msgRet.camp = camp
	msgRet.lvRed = lvRed and 1 or 0
	msgRet.qualityRed = qualityRed and 1 or 0

	--Msg.trace(msgRet)
	Msg.send(msgRet,human.fd)
end

local function makeXyPowerLvNet(human,net,camp)
	net.camp = camp
	local db = getPowerData(human,camp)
	net.lv = db and db.lv or 0
end

function CG_XINGYAOMEN_POWER_QUERY(human)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	local defineCnf = XingYaoMenExcel.powerDefine[1]

	local msgRet = Msg.gc.GC_XINGYAOMEN_POWER_QUERY
	msgRet.lvs[0] = #defineCnf.camps
	for i=1,#defineCnf.camps do
		local camp = defineCnf.camps[i]
		makeXyPowerLvNet(human,msgRet.lvs[i],camp)
	end

	msgRet.reds[0] = #defineCnf.camps
	for camp=1,#defineCnf.camps do
		msgRet.reds[camp] = 0
		if lvRed(human,camp) or qualityRed(human,camp) then
			msgRet.reds[camp] = 1
		end
	end

	--Msg.trace(msgRet)
	Msg.send(msgRet,human.fd)

	RoleSystemLogic.sendSystemReds(human, RoleSystemDefine.ROLE_SYS_ID_404)
end

local function checkCamp(camp)
	local defineCnf = XingYaoMenExcel.powerDefine[1]
	for i=1,#defineCnf.camps do
		if camp == defineCnf.camps[i] then
			return true
		end
	end
end

local function makeLvAttrs(human,net,camp)
	local db = getPowerData(human,camp)
	local nowLV = db and db.lv or 0

	net.attrs[0] = 0
	local conf = XingYaoMenExcel.powerLv[nowLV]
	local attrs = nil
	if conf then
		for i=1,#conf.attrs do
			local key = conf.attrs[i][1]
			local value = conf.attrs[i][2]

			attrs = attrs or {}
			attrs[key] = (attrs[key] or 0) + value
		end
	end

	if db and db.lvAttrs then
		for key,value in pairs(db.lvAttrs) do
			attrs = attrs or {}
			attrs[key] = (attrs[key] or 0) + value
		end
	end

	if attrs then
		for key,value in pairs(attrs) do
			net.attrs[0] = net.attrs[0] + 1
			local index = net.attrs[0]
			net.attrs[index].key = key
			net.attrs[index].value = value
		end
	end

	local defConf = XingYaoMenExcel.powerDefine[1]
	net.attrsShow[0] = #defConf.powerLvAttrs
	for i=1,#defConf.powerLvAttrs do
		net.attrsShow[i].key = defConf.powerLvAttrs[i]
		net.attrsShow[i].value = 0
	end
end

local function makeQualityAttrs(human,net,camp)
	local db = getPowerData(human,camp)
	local qualityID = db and db.qualityID or 0
	net.attrs[0] = 0
	local attrs = {}
	if qualityID > 0 then
		for i=1,qualityID do
			local conf = XingYaoMenExcel.powerQuality[i]
			if conf then
				for j=1,#conf.attrs do
					local key = conf.attrs[j][1]
					local value = conf.attrs[j][2]
					attrs[key] = (attrs[key] or 0) + value
				end
			end
		end
	end
	for key,value in pairs(attrs) do
		net.attrs[0] = net.attrs[0] + 1
		local index = net.attrs[0]
		net.attrs[index].key = key
		net.attrs[index].value = value
	end	

	local defConf = XingYaoMenExcel.powerDefine[1]
	net.attrsShow[0] = #defConf.powerQualitAttrs
	for i=1,#defConf.powerQualitAttrs do
		net.attrsShow[i].key = defConf.powerQualitAttrs[i]
		net.attrsShow[i].value = 0
	end
end

function CG_XINGYAOMEN_POWERLV_QUERY(human,camp)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	if not checkCamp(camp) then return end

	local msgRet = Msg.gc.GC_XINGYAOMEN_POWERLV_QUERY
	makeXyPowerLvNet(human,msgRet.lv,camp)
	
	local db = getPowerData(human,camp)
	local nowExp = db and db.exp or 0
	local nowLV = db and db.lv or 0

	local conf = XingYaoMenExcel.powerLv
	local nextLV = math.min(nowLV + 1,#conf) 
	local nextConf = conf[nextLV]

	msgRet.nowExp = nowExp
	msgRet.needExp = nextConf.needExp
	
	makeLvAttrs(human,msgRet.lvAttrs,camp)
	makeQualityAttrs(human,msgRet.qualityAttrs,camp)
	
	msgRet.upCost[0] = 0
	msgRet.nextAttrs[0] = 0
	if nowLV < #conf then
		msgRet.upCost[0] = 2
		local campsLVupItem = XingYaoMenExcel.powerDefine[1].campsLVupItem[camp]
		Grid.makeItem(msgRet.upCost[1],campsLVupItem,nextConf.upCost)
		Grid.makeItem(msgRet.upCost[2],ItemDefine.ITEM_JINBI_ID,nextConf.upCostJinBi)

		local attrsAdd = nextConf.attrsAdd
		for _,attr in pairs(attrsAdd) do
			msgRet.nextAttrs[0] = msgRet.nextAttrs[0] + 1
			local index = msgRet.nextAttrs[0]
			msgRet.nextAttrs[index].key = attr[1]
			msgRet.nextAttrs[index].value = attr[2]
		end
	end

	--Msg.trace(msgRet)
	Msg.send(msgRet,human.fd)

	GC_XINGYAOMEN_POWER_REDS(human,camp)
end

function CG_XINGYAOMEN_POWERLV_UP(human,camp)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	if not checkCamp(camp) then return end

	local db = getPowerData(human,camp)
	local nowLV = db and db.lv or 0
	local conf = XingYaoMenExcel.powerLv

	if nowLV >= #conf then return end

	local defConf = XingYaoMenExcel.powerDefine[1]

	local campsLVupItem = defConf.campsLVupItem[camp]
	local nextConf = conf[nowLV+1]
	local upCost = nextConf.upCost
	if not BagLogic.checkItemCnt(human, campsLVupItem, upCost) then return end
	if not BagLogic.checkItemCnt(human, ItemDefine.ITEM_JINBI_ID, nextConf.upCostJinBi) then return end

	BagLogic.delItem(human, campsLVupItem, upCost, "xingyao_power")
	BagLogic.delItem(human, ItemDefine.ITEM_JINBI_ID, nextConf.upCostJinBi, "xingyao_power")

	local powerLvUpExp = defConf.powerLvUpExp

	human.db.XingYaoPower = human.db.XingYaoPower or {}
	human.db.XingYaoPower[camp] = human.db.XingYaoPower[camp] or {}
	human.db.XingYaoPower[camp].exp = (human.db.XingYaoPower[camp].exp or 0) + powerLvUpExp
	if human.db.XingYaoPower[camp].exp >= nextConf.needExp then
		human.db.XingYaoPower[camp].lv = nowLV + 1
		human.db.XingYaoPower[camp].lvAttrs = nil
		human.db.XingYaoPower[camp].exp = 0
	else
		local attrsAdd = nextConf.attrsAdd
		for _,attr in pairs(attrsAdd) do
			human.db.XingYaoPower[camp].lvAttrs = human.db.XingYaoPower[camp].lvAttrs or {}
			human.db.XingYaoPower[camp].lvAttrs[attr[1]] = (human.db.XingYaoPower[camp].lvAttrs[attr[1]] or 0) + attr[2]
		end
	end

	ObjHuman.doCalcHeros(human)
	CG_XINGYAOMEN_POWERLV_QUERY(human,camp)
	GC_XINGYAOMEN_POWER_REDS(human,camp)

	RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_404)
	RoleSystemLogic.sendSystemReds(human, RoleSystemDefine.ROLE_SYS_ID_10042)
end

function getQualityMax(human,camp)
	local db = getPowerData(human,camp)
	local nowLV = db and db.lv or 0
	local conf = XingYaoMenExcel.powerLv

	if not conf[nowLV] then return 0,0 end

	local qualityMax = conf[nowLV].qualityMax
	local qualityMaxID = 0
	for qualityID,data in ipairs(XingYaoMenExcel.powerQuality) do
		if data.quality == qualityMax then
			qualityMaxID = qualityID
		end
	end
	
	return qualityMax + 1,qualityMaxID + 1
end

local function getQualityCanUp(human,camp)
	local db = getPowerData(human,camp)
	local qualityID = db and db.qualityID or 0
	local conf = XingYaoMenExcel.powerLv
	local qualityConf = XingYaoMenExcel.powerQuality
	local quality = qualityConf[qualityID] and qualityConf[qualityID].quality or 0
	local star = qualityConf[qualityID] and qualityConf[qualityID].star or 0

	if star == 0 then
		quality = quality - 1
	end	

	for lv,data in ipairs(conf) do
		if quality < data.qualityMax then
			return lv
		end
	end

	return 0
end

function CG_XINGYAOMEN_POWERQUALITY_QUERY(human,camp)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	if not checkCamp(camp) then return end

	local msgRet = Msg.gc.GC_XINGYAOMEN_POWERQUALITY_QUERY
	makeXyPowerLvNet(human,msgRet.lv,camp)
	makeLvAttrs(human,msgRet.lvAttrs,camp)
	makeQualityAttrs(human,msgRet.qualityAttrs,camp)

	local db = getPowerData(human,camp)
	local qualityID = db and db.qualityID or 0
	local conf = XingYaoMenExcel.powerQuality
	local quality = 0
	local star = 0
	if conf[qualityID] then
		quality,star = conf[qualityID].quality,conf[qualityID].star
	end

	msgRet.lvCanUp = 0
	msgRet.upCost[0] = 0
	msgRet.nextAttrs[0] = 0

	local qualityMax,qualityMaxID = getQualityMax(human,camp)

	if qualityID >= qualityMaxID then
		msgRet.lvCanUp = getQualityCanUp(human,camp)
	end
	
	msgRet.quality = quality
	msgRet.star = star
	
	if conf[qualityID+1] and qualityID < qualityMaxID then
		local upCost = conf[qualityID+1].upCost
		msgRet.upCost[0] = #upCost

		for i=1,#upCost do
			Grid.makeItem(msgRet.upCost[i],upCost[i][1],upCost[i][2])
		end

		local attrs = conf[qualityID+1].attrs
		msgRet.nextAttrs[0] = #attrs
		for i=1,#attrs do
			msgRet.nextAttrs[i].key = attrs[i][1]
			msgRet.nextAttrs[i].value = attrs[i][2]
		end
	end

	--Msg.trace(msgRet)
	Msg.send(msgRet,human.fd)
end

function CG_XINGYAOMEN_POWERQUALITY_UP(human,camp)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	if not checkCamp(camp) then return end

	local db = getPowerData(human,camp)
	local qualityID = db and db.qualityID or 0
	local qualityMax,qualityMaxID = getQualityMax(human,camp)
	local conf = XingYaoMenExcel.powerQuality
	local quality = conf[qualityID] and conf[qualityID].quality or 0
	if qualityID >= #conf or qualityID >= qualityMaxID then return end

	local upCost = conf[qualityID+1].upCost
	for _,item in pairs(upCost) do
		if not BagLogic.checkItemCnt(human, item[1], item[2]) then return end
	end

	for _,item in pairs(upCost) do
		BagLogic.delItem(human, item[1], item[2], "xingyao_power")
	end

	human.db.XingYaoPower = human.db.XingYaoPower or {}
	human.db.XingYaoPower[camp] = human.db.XingYaoPower[camp] or {}
	human.db.XingYaoPower[camp].qualityID = qualityID + 1

	ObjHuman.doCalcHeros(human)
	CG_XINGYAOMEN_POWERQUALITY_QUERY(human,camp)
	GC_XINGYAOMEN_POWER_REDS(human,camp)

	RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_404)
	RoleSystemLogic.sendSystemReds(human, RoleSystemDefine.ROLE_SYS_ID_10042)
end

local function getQualityBack(human,camp)
	local db = getPowerData(human,camp)
	local qualityID = db and db.qualityID or 0

	local conf = XingYaoMenExcel.powerQuality
	local backItem = nil
	if qualityID > 0 then
		backItem = {}
		for i=1,qualityID do
			local upCost = conf[i].upCost
			for j=1,#upCost do
				backItem[upCost[j][1]] = (backItem[upCost[j][1]] or 0) + upCost[j][2]
			end
		end
	end

	return backItem
end

function CG_XINGYAOMEN_POWERQUALITY_RESET(human,camp)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	ObjHuman.updateDaily(human)

	local defineCnf = XingYaoMenExcel.powerDefine[1]

	local msgRet = Msg.gc.GC_XINGYAOMEN_POWERQUALITY_RESET
	msgRet.resetMax = defineCnf.resetCnt

	local resetCnt = human.db.XingYaoPower and human.db.XingYaoPower.resetCnt or 0
	msgRet.resetLeft = defineCnf.resetCnt - resetCnt
	Grid.makeItem(msgRet.resetCost,defineCnf.resetCost[1],defineCnf.resetCost[2])

	local backItem = getQualityBack(human,camp)
	msgRet.backItem[0] = 0
	if backItem then
		for itemID,itemCnt in pairs(backItem) do
			msgRet.backItem[0] = msgRet.backItem[0] + 1
			local index = msgRet.backItem[0]
			Grid.makeItem(msgRet.backItem[index],itemID,itemCnt)
		end
	end

	--Msg.trace(msgRet)
	Msg.send(msgRet,human.fd)
end

function CG_XINGYAOMEN_POWERQUALITY_RESET_DO(human,camp)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	if not checkCamp(camp) then return end

	ObjHuman.updateDaily(human)

	local defineCnf = XingYaoMenExcel.powerDefine[1]
	if not BagLogic.checkItemCnt(human,defineCnf.resetCost[1],defineCnf.resetCost[2]) then return end

	BagLogic.delItem(human,defineCnf.resetCost[1],defineCnf.resetCost[2],"xingyao_power")

	local resetCnt = human.db.XingYaoPower and human.db.XingYaoPower.resetCnt or 0
	local resetLeft = defineCnf.resetCnt - resetCnt
	if resetLeft <= 0 then
		return Broadcast.sendErr(human,Lang.XINGYAOMEN_RESETCNT_ERR)
	end

	local db = getPowerData(human,camp)
	local qualityID = db and db.qualityID or 0
	if qualityID == 0 then
		return Broadcast.sendErr(human,Lang.XINGYAOMEN_RESET_ERR)
	end

	local backItem = getQualityBack(human,camp)
	if not backItem then return end
	for itemID,itemCnt in pairs(backItem) do
		BagLogic.addItem(human,itemID,itemCnt,"xingyao_power")	
	end

	human.db.XingYaoPower = human.db.XingYaoPower or {}
	human.db.XingYaoPower.resetCnt = resetCnt + 1
	human.db.XingYaoPower[camp].qualityID = nil

	ObjHuman.doCalcHeros(human)
	CG_XINGYAOMEN_POWERQUALITY_RESET(human,camp)
	CG_XINGYAOMEN_POWERQUALITY_QUERY(human,camp)
	GC_XINGYAOMEN_POWER_REDS(human,camp)

	RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_404)
	RoleSystemLogic.sendSystemReds(human, RoleSystemDefine.ROLE_SYS_ID_10042)
end

function CG_XINGYAOMEN_POWERQUALITY_ATTRS(human,camp)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_10042,true) then
		return
	end

	if not checkCamp(camp) then return end

	local msgRet = Msg.gc.GC_XINGYAOMEN_POWERQUALITY_ATTRS
	msgRet.camp = camp
	local defConf = XingYaoMenExcel.powerDefine[1]
	msgRet.attrsShow[0] = #defConf.powerQualitAttrs
	for i=1,#defConf.powerQualitAttrs do
		msgRet.attrsShow[i].key = defConf.powerQualitAttrs[i]
		msgRet.attrsShow[i].value = 0
	end

	msgRet.showList[0] = 0
	local list = {}
	for key,data in ipairs(XingYaoMenExcel.powerQuality) do
		local quality = data.quality
		if data.star ~= 0 then
			quality = quality + 1
		end
		list[quality] = list[quality] or {}
		for _,attr in pairs(data.attrs) do
			local key = attr[1]
			local value = attr[2]
			list[quality] = list[quality] or {}
			list[quality][key] = (list[quality][key] or 0) + value
		end
	end

	for i=1,#list do
		local allAttrs = {}
		msgRet.showList[0] = msgRet.showList[0] + 1
		local index = msgRet.showList[0]
		msgRet.showList[index].quality = i
		msgRet.showList[index].attrs[0] = 0
		for j=1,#list do
			if j <= i then
				for key,value in pairs(list[j]) do
					allAttrs[key] = (allAttrs[key] or 0)  + value
				end
			end
		end

		for key,value in pairs(allAttrs) do
			msgRet.showList[index].attrs[0] = msgRet.showList[index].attrs[0] + 1
			local attrIndex = msgRet.showList[index].attrs[0]
			msgRet.showList[index].attrs[attrIndex].key = key
			msgRet.showList[index].attrs[attrIndex].value = value
		end
	end

	--Msg.trace(msgRet)
	Msg.send(msgRet,human.fd)
end

function lvRed(human,camp)
	local db = getPowerData(human,camp)
	local nowLV = db and db.lv or 0
	local conf = XingYaoMenExcel.powerLv

	if nowLV >= #conf then return end

	local nextConf = conf[nowLV+1]
	local upCost = nextConf.upCost
	local campsLVupItem = XingYaoMenExcel.powerDefine[1].campsLVupItem[camp]
	local now = BagLogic.getItemCnt(human,campsLVupItem)
	if upCost > now then return end
	if human.db.jinbi < nextConf.upCostJinBi then return end

	return true
end

function qualityRed(human,camp)
	local db = getPowerData(human,camp)
	local qualityID = db and db.qualityID or 0
	local qualityMax,qualityMaxID = getQualityMax(human,camp)
	local conf = XingYaoMenExcel.powerQuality
	local quality = conf[qualityID] and conf[qualityID].quality or 0
	if qualityID >= #conf or qualityID >= qualityMaxID then return end

	local upCost = conf[qualityID+1].upCost
	for _,item in pairs(upCost) do
		local now = BagLogic.getItemCnt(human,item[1])
		if item[2] > now then return end
	end

	return true
end

function isDot(human)
	local defineCnf = XingYaoMenExcel.powerDefine[1]
	for camp=1,#defineCnf.camps do
		local lvRed = lvRed(human,camp)
		if lvRed then return true end

		local qualityRed = qualityRed(human,camp)
		if qualityRed then return true end
	end
end

function doCalcHero(human,heroGrid,attrs)
	if not human then return end
	
	local cf = HeroExcel.hero[heroGrid.id]
	local camp = cf.camp
	if not checkCamp(camp) then return end
	local db = getPowerData(human,camp)
	if not db then return end

	local defineCnf = XingYaoMenExcel.powerDefine[1]
	local attrsList = {}
	local nowLV = db and db.lv or 0

	local powerConf = XingYaoMenExcel.powerLv[nowLV]
	if powerConf then
		for i=1,#powerConf.attrs do
			local key = powerConf.attrs[i][1]
			local value = powerConf.attrs[i][2]

			attrsList[key] = (attrsList[key] or 0) + value
		end
	end

	if db and db.lvAttrs then
		for key,value in pairs(db.lvAttrs) do
			attrsList[key] = (attrsList[key] or 0) + value
		end
	end

	local qualityID = db and db.qualityID or 0
	if qualityID > 0 then
		for i=1,qualityID do
			local qualityConf = XingYaoMenExcel.powerQuality[i]
			if qualityConf then
				for j=1,#qualityConf.attrs do
					local key = qualityConf.attrs[j][1]
					local value = qualityConf.attrs[j][2]
					attrsList[key] = (attrsList[key] or 0) + value
				end
			end
		end
	end

	for key,value in pairs(attrsList) do
		RoleAttr.updateValue(key,value,attrs)
	end
end